<?php

/**
 * The main router of the application. Sets up the basics for the controller and
 * then loads the requested controller. 
 *
 * @author Niels Janssen
 * @since 2009-03-17
 */
class ApplicationController extends Controller
{

	/**
	 * @see Controller::defaultAction()
	 *
	 */	
	public function defaultAction()
	{
		$this->prepareTemplatingEngine();
		
		$userAuthenticated = $this->authenticateUser();
		
		$target = $this->getTarget();
		
		if( $target->requiresAuthentication() && !$userAuthenticated )
		{
			$target = $this->routeToLogin();
		}
		else
		{
			$this->routeToTarget( $target );
		}
		
		$this->renderOutput( $target );
	}
	
	/**
	 * Prepare smarty.
	 * 
	 */
	public function prepareTemplatingEngine()
	{
		$this->smarty = new Smarty();
		$this->smarty->template_dir	= 'Templates';
		$this->smarty->compile_dir	= 'Templates/Compiled';
	}
	
	/**
	 * Authenticates the user and returns whether or not the authentication
	 * has succeeded.
	 *
	 * @return boolean
	 */
	public function authenticateUser()
	{

		return null != User::authenticate();
	}
	
	/**
	 * Routs to the login controller.
	 *
	 * @return Controller
	 */
	public function routeToLogin()
	{
		require_once 'System/Controllers/LoginController.php';
		$controller = new LoginController( null, $this->getSmarty() );
		$controller->defaultAction();
		return $controller;
	}
	
	/**
	 * Gets the target controller
	 *
	 * @return Controller
	 */
	public function getTarget()
	{
		$controllerToBeInvoked	= isset( $_GET['c'] ) ? Inflector::camelize( str_replace( '-', '_', $_GET['c'] ) ) : '';
		$controllerPath = 'System/Controllers/' . $controllerToBeInvoked . 'Controller.php';
		
		if( is_file( $controllerPath ) )
		{
			require_once $controllerPath;
		}
		
		if( empty( $controllerToBeInvoked ) || !class_exists( $controllerToBeInvoked . 'Controller', false ) )
		{
			if( !class_exists( 'DefaultController', true ) )
			{
				throw new PageNotFoundException( "Controller '" . $controllerToBeInvoked . "' was not found, default controller could not be loaded" );
			}
			
			$controllerToBeInvoked = 'Default';
		}
		
		$controllerToBeInvoked .= 'Controller';
		return new $controllerToBeInvoked ( User::getInstance(), $this->getSmarty() );
	}
	
	/**
	 * Routs to the target controller. It figures out the action to be executed
	 * and executes it.
	 *
	 * @param Controller $target
	 */
	public function routeToTarget( Controller $target )
	{
		/**
		 * Determine the controller and action and initialize.
		 */
		$actionToBeInvoked		= isset( $_GET['a'] ) ? Inflector::camelize( str_replace( '-', '_', $_GET['a'] ) ) : '';
		
		if( empty( $actionToBeInvoked ) )
		{
			$actionToBeInvoked = 'default';
		}
		
		if( !method_exists( $target, $actionToBeInvoked . 'Action' ) )
		{
			throw new PageNotFoundException( 'Controller "' . get_class( $target ) . '" does not support the "' . $actionToBeInvoked . '" action.' );
		}
		
		$actionToBeInvoked .= 'Action';
		
		$target->$actionToBeInvoked();
	}
	
	/**
	 * Renders the output of the controller.
	 *
	 * @param Controller $target
	 */
	private function renderOutput( Controller $target )
	{
		$mainView = new HTMLView('MainUI.tpl', $this->getSmarty());
		$content = $target->getViewManager()->render();
		
		$mainView->assign( 'content', $content );
		echo $mainView->render();
	}
}

class PageNotFoundException extends Exception{}